package com.woniu108.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu108.carService.commos.dto.*;
import com.woniu108.carService.commos.exception.WoniuException;
import com.woniu108.carService.commos.exception.orderProduct.OrderProductException;
import com.woniu108.carService.commos.exception.orderProduct.OrderProductExceptionCode;
import com.woniu108.carService.commos.exception.orderService.OrderServiceException;
import com.woniu108.carService.commos.exception.orderService.OrderServiceExceptionCode;
import com.woniu108.carService.commos.exception.produnt.ProductException;
import com.woniu108.carService.commos.model.PagePayParam;
import com.woniu108.carService.commos.model.Result;
import com.woniu108.carService.commos.util.*;
import com.woniu108.order.client.ExtraClient;
import com.woniu108.order.client.PersonClient;
import com.woniu108.order.client.ProductClient;
import com.woniu108.order.client.ValueAddedClient;
import com.woniu108.order.mapper.OrderDeleteMapper;
import com.woniu108.order.mapper.OrderProductMapper;
import com.woniu108.order.model.dto.OrderProductDto;
import com.woniu108.order.model.form.GetOneUserForm;
import com.woniu108.order.model.form.OrderProductUpdateReviewStateForm;
import com.woniu108.order.model.model.OrderDelete;
import com.woniu108.order.model.model.OrderProduct;
import com.woniu108.order.model.param.OrderProductCancelParam;
import com.woniu108.order.model.param.OrderProductCreateParam;
import com.woniu108.order.model.param.OrderProductUpdateAddressParam;
import com.woniu108.order.model.param.QueryOrderProductConditionParam;
import com.woniu108.order.service.OrderProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu108.product.form.FailedSaleForm;
import com.woniu108.product.form.SuccessfulOrderForm;
import com.woniu108.product.form.SuccessfulSaleForm;
import org.apache.catalina.User;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.PipedReader;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 商品订单表 服务实现类
 * </p>
 *
 * @author yanxi
 * @since 2024-05-23
 */
@Service
public class OrderProductServiceImpl extends ServiceImpl<OrderProductMapper, OrderProduct> implements OrderProductService {
    @Resource
    private OrderProductMapper orderProductMapper;
    @Resource
    private OrderDeleteMapper orderDeleteMapper;

    @Resource
    private PersonClient personClient;
    @Resource
    private ExtraClient extraClient;
    @Resource
    private ProductClient productClient;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ValueAddedClient valueAddedClient;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private AlipayUtil alipayUtil;
    @Resource
    private AlipayConfiguration alipayConfiguration;
    @Resource
    private AlipayClient alipayClient;

    /**
     * 获取商品订单中的商品清单
     * @param orderNum 订单编号
     * @return 商品清单
     */
    public ArrayList<Map<Object,Object>> selectProductInfosByOrderProductNum(String orderNum){
        ArrayList<Map<Object, Object>> maps = new ArrayList<>();
        Set<Object> set = redisUtil.sMembers(RedisKey.orderProductPInfoSet(orderNum));
        for (Object s:set){
            Integer pInfoId=Integer.parseInt(s.toString());
            Map<Object, Object> map = redisUtil.hgetall(RedisKey.orderProductPInfoByNumHash(orderNum, pInfoId));
            maps.add(map);
        }
        return maps;
    }

    @Override
    public Page<OrderProductDto> selectOrderByConditionToManager(QueryOrderProductConditionParam param) {
        QueryWrapper<OrderProduct> queryWrapper = new QueryWrapper<>();

        //根据phone，nickName，realName查询用户信息
        UserInfoDto userInfoDto = new UserInfoDto();
        if (ObjectUtil.isNotEmpty(param.getUserNickName())|| ObjectUtil.isNotEmpty(param.getUserRealName()) || ObjectUtil.isNotEmpty(param.getUserPhone())) {
            GetOneUserForm form = BeanUtil.toBean(param, GetOneUserForm.class);
            System.out.println(form.toString());
            Result<UserInfoDto> userInfoDtoResult = personClient.getOneUser(form);
            if (userInfoDtoResult.getCode() != 200) {
                throw new OrderProductException(500, "角色信息报错");
            }
            userInfoDto = userInfoDtoResult.getData();
            System.out.println(userInfoDto);
            param.setUserId(userInfoDto.getUserId());
        }

        //按下单时间查询
        if (ObjectUtil.isNotEmpty(param.getOrderMinTime())) {
            queryWrapper.ge("order_time", DateUtil.parse(param.getOrderMinTime(), "yyyy-MM-dd HH:mm:ss").toString());
        }
        if(ObjectUtil.isNotEmpty(param.getOrderMaxTime())){
            queryWrapper.le("order_time",DateUtil.parse(param.getOrderMaxTime(), "yyyy-MM-dd HH:mm:ss").toString());
        }
        if (ObjectUtil.isNotEmpty(param.getPayMinTime())) {
            queryWrapper.ge("pay_time",DateUtil.parse(param.getPayMinTime(), "yyyy-MM-dd HH:mm:ss").toString());
        }
        if(ObjectUtil.isNotEmpty(param.getPayMaxTime())){
            queryWrapper.le("pay_time",DateUtil.parse(param.getPayMaxTime(), "yyyy-MM-dd HH:mm:ss").toString());
        }
        if (ObjectUtil.isNotEmpty(param.getUserId())) {
            queryWrapper.eq("user_id", param.getUserId());
        }
        if (ObjectUtil.isNotEmpty(param.getOrderProductNum())) {
            queryWrapper.like("order_product_num", param.getOrderProductNum());
        }
        if (ObjectUtil.isNotEmpty(param.getOrderProductState() )) {
            queryWrapper.eq("order_product_state", param.getOrderProductState());
        }


        Page<OrderProduct> page = new Page<>(param.getPageNum(), param.getPageSize());
        orderProductMapper.selectPage(page, queryWrapper);

        Page<OrderProductDto> dtoPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        ArrayList<OrderProductDto> orderProductDtos = new ArrayList<>();
        if (page.getRecords() != null) {
            for (OrderProduct orderProduct : page.getRecords()) {
                OrderProductDto orderProductDto = BeanUtil.toBean(orderProduct, OrderProductDto.class);
                Result<UserInfoDto> userInfoDtoResult = personClient.getByUserId(orderProductDto.getUserId());
                if (userInfoDtoResult.getCode() != 200) {
                    throw new OrderProductException(userInfoDtoResult.getCode(), userInfoDtoResult.getMsg());
                }
                UserInfoDto dto = userInfoDtoResult.getData();
                orderProductDto.setUserInfoDto(dto);
                Result<AddressInfoDto> addressInfoDtoResult = extraClient.AddressInfoById(orderProduct.getAddressId());
                if (addressInfoDtoResult.getCode() != 200) {
                    throw new OrderProductException(500, "地址信息异常");
                }
                orderProductDto.setAddressInfoDto(addressInfoDtoResult.getData());
                //如果订单已取消
                if (orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_CANCELED)) {
                    OrderDelete orderDelete = orderDeleteMapper.selectById(orderProductDto.getOrderProductNum());
                    //插入取消理由
                    orderProductDto.setDeleteReason(orderDelete.getDeleteReason());
                }
                //获取商品清单
                ArrayList<Map<Object, Object>> maps = selectProductInfosByOrderProductNum(orderProductDto.getOrderProductNum());
                orderProductDto.setProductInfos(maps);

                orderProductDtos.add(orderProductDto);
            }
            dtoPage.setRecords(orderProductDtos);
        }
        return dtoPage;
    }

    @Override
    public Page<OrderProductDto> selectOrderByCondition(QueryOrderProductConditionParam param) {
        QueryWrapper<OrderProduct> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", param.getUserId());

        //按下单时间查询
        if (ObjectUtil.isNotEmpty(param.getOrderMinTime())) {
            queryWrapper.ge("order_time", DateUtil.parse(param.getOrderMinTime(), "yyyy-MM-dd HH:mm:ss").toString());
        }
        if(ObjectUtil.isNotEmpty(param.getOrderMaxTime())){
            queryWrapper.le("order_time",DateUtil.parse(param.getOrderMaxTime(), "yyyy-MM-dd HH:mm:ss").toString());
        }
        if (ObjectUtil.isNotEmpty(param.getPayMinTime())) {
            queryWrapper.ge("pay_time",DateUtil.parse(param.getPayMinTime(), "yyyy-MM-dd HH:mm:ss").toString());
        }
        if(ObjectUtil.isNotEmpty(param.getPayMaxTime())){
            queryWrapper.le("pay_time",DateUtil.parse(param.getPayMaxTime(), "yyyy-MM-dd HH:mm:ss").toString());
        }
        //订单编号模糊查询
        if (ObjectUtil.isNotEmpty(param.getOrderProductNum())) {
            queryWrapper.like("order_product_num", param.getOrderProductNum());
        }
        if (ObjectUtil.isNotEmpty(param.getOrderProductState())) {
            //排除用户查询自己已删除的订单
            if (param.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_DELETED)) {
                throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_DELETED_NO_SELECT);
            }
            queryWrapper.eq("order_product_state", param.getOrderProductState());
        }

        Page<OrderProduct> page = new Page<>(param.getPageNum(), param.getPageSize());
        orderProductMapper.selectPage(page, queryWrapper);

        Page<OrderProductDto> dtoPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        ArrayList<OrderProductDto> orderProductDtos = new ArrayList<>();
        for (OrderProduct orderProduct : page.getRecords()) {
            OrderProductDto orderProductDto = BeanUtil.toBean(orderProduct, OrderProductDto.class);
            UserInfoDto userInfoDto = new UserInfoDto();
            if (param.getUserId() == null) {
                Result<UserInfoDto> userInfoDtoResult = personClient.getByUserId(orderProductDto.getUserId());
                if (userInfoDtoResult.getCode() != 200) {
                    throw new OrderProductException(userInfoDtoResult.getCode(), userInfoDtoResult.getMsg());
                }
                UserInfoDto dto = userInfoDtoResult.getData();
            }
            orderProductDto.setUserInfoDto(userInfoDto);
            Result<AddressInfoDto> addressInfoDtoResult = extraClient.AddressInfoById(orderProduct.getAddressId());
            if (addressInfoDtoResult.getCode() != 200) {
                throw new OrderProductException(500, "地址信息异常");
            }
            orderProductDto.setAddressInfoDto(addressInfoDtoResult.getData());
            //如果订单已取消
            if (orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_CANCELED)) {
                OrderDelete orderDelete = orderDeleteMapper.selectById(orderProductDto.getOrderProductNum());
                //插入取消理由
                orderProductDto.setDeleteReason(orderDelete.getDeleteReason());
            }
            //获取商品清单
            ArrayList<Map<Object, Object>> maps = selectProductInfosByOrderProductNum(orderProductDto.getOrderProductNum());
            orderProductDto.setProductInfos(maps);

            orderProductDtos.add(orderProductDto);
        }
        dtoPage.setRecords(orderProductDtos);
        return dtoPage;
    }

    @Override
    public OrderProductDto selectOneOrderByOrderNum(String orderNum) {
        //主键查询
        OrderProduct orderProduct = orderProductMapper.selectOne(new QueryWrapper<OrderProduct>().eq("order_product_num",orderNum));
        System.out.println(orderProduct);
        OrderProductDto orderProductDto = BeanUtil.toBean(orderProduct, OrderProductDto.class);

        //查询用户信息
        Result<UserInfoDto> userInfoDtoResult = personClient.getByUserId(orderProductDto.getUserId());
        if (userInfoDtoResult.getCode() != 200) {
            throw new OrderProductException(userInfoDtoResult.getCode(), userInfoDtoResult.getMsg());
        }
        //插入用户信息
        UserInfoDto dto = userInfoDtoResult.getData();
        orderProductDto.setUserInfoDto(dto);

        //查询地址信息
        Result<AddressInfoDto> addressInfoDtoResult = extraClient.AddressInfoById(orderProduct.getAddressId());
        if (addressInfoDtoResult.getCode() != 200) {
            throw new OrderProductException(500, "地址信息异常");
        }
        //插入地址信息
        orderProductDto.setAddressInfoDto(addressInfoDtoResult.getData());

        //如果订单已取消
        if (orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_CANCELED)) {
            OrderDelete orderDelete = orderDeleteMapper.selectById(orderNum);
            //插入取消理由
            orderProductDto.setDeleteReason(orderDelete.getDeleteReason());
        }
        //查询订单中的商品清单
        ArrayList<Map<Object, Object>> maps = new ArrayList<>();
        Set<Object> set = redisUtil.sMembers(RedisKey.orderProductPInfoSet(orderNum));
        for (Object s:set){
            Integer pInfoId=Integer.parseInt(s.toString());
            Map<Object, Object> map = redisUtil.hgetall(RedisKey.orderProductPInfoByNumHash(orderNum, pInfoId));
            maps.add(map);
        }
        //插入商品订单
        orderProductDto.setProductInfos(maps);

        return orderProductDto;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void cancelOrderByOrderNum(OrderProductCancelParam param) {
        OrderProduct orderProduct = orderProductMapper.selectOne(new QueryWrapper<OrderProduct>().eq("order_product_num",param.getOrderProductNum()));

        if (!orderProduct.getUserId().equals(param.getUserId())) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_USER_NOT_POWER);
        }
        //只有在订单还未支付时才能取消
        if (!orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_NO_PAID)) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_NO_CANCEL);
        }

        orderProduct.setOrderProductState(StaticData.ORDER_PRODUCT_STATE_CANCELED);
        orderProductMapper.updateById(orderProduct);

        OrderDelete orderDelete = BeanUtil.toBean(orderProduct, OrderDelete.class);
        orderDelete.setOrderProductNum(param.getOrderProductNum());
        orderDelete.setDeleteReason(param.getDeleteReason());
        orderDelete.setDeleteTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new DateTime()));
        orderDelete.setDealTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new DateTime()));
        orderDelete.setDeleteReason(param.getDeleteReason());
        orderDelete.setDeleteState(1);
        orderDeleteMapper.insert(orderDelete);

        //该冻结量还余量
        ArrayList<Map<Object, Object>> maps = new ArrayList<>();
        Set<Object> set = redisUtil.sMembers(RedisKey.orderProductPInfoSet(param.getOrderProductNum()));
        for (Object s:set){
            Integer pInfoId=Integer.parseInt(s.toString());
            Map<Object, Object> map = redisUtil.hgetall(RedisKey.orderProductPInfoByNumHash(param.getOrderProductNum(), pInfoId));
            maps.add(map);
        }
        for (Map<Object,Object> map:maps){
            FailedSaleForm form = new FailedSaleForm();
            form.setPInfoId(Integer.valueOf(map.get("pInfoId").toString()) );
            form.setNum(Integer.valueOf(map.get("number").toString()) );
            productClient.failedSale(form);
            productClient.submitFreezeNum(form);
        }
    }

    @Override
    public void updateAddressByOrderProduct(OrderProductUpdateAddressParam param) {
        OrderProduct orderProduct = orderProductMapper.selectOne(new QueryWrapper<OrderProduct>().eq("order_product_num",param.getOrderNum()));

        if (!orderProduct.getUserId().equals(param.getUserId())) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_USER_NOT_POWER);
        }
        if (orderProduct.getOrderProductState() >= StaticData.ORDER_PRODUCT_STATE_NO_GET) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_USER_NOT_UPDATE_ADDRESS);
        }

        //查询地址信息
        Result<AddressInfoDto> addressInfoDtoResult = extraClient.AddressInfoById(orderProduct.getAddressId());
        if (addressInfoDtoResult.getCode() != 200) {
            throw new OrderProductException(500, "地址信息异常");
        }
        AddressInfoDto data = addressInfoDtoResult.getData();
        if (data == null) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_RE_ADDRESS_NO_EXISTED);
        }
        if (data.getUserId() != param.getUserId()) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_USER_NO_HAVE_ADDRESS);
        }

        orderProduct.setAddressId(param.getAddressId());
        orderProductMapper.updateById(orderProduct);
    }

    /**
     * 用户下单
     *
     * @param param 下单需求
     * @return Boolean
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean createOrderByProduct(OrderProductCreateParam param) {
        Result<List<UserCartDto>> listResult = productClient.findUserCartByUserId(param.getUserId());
        if (listResult.getCode() != 200) {
            throw new WoniuException(listResult.getMsg(), listResult.getCode());
        }
        List<UserCartDto> cartDtos = listResult.getData();
        if (cartDtos == null) {
            throw new OrderProductException(OrderProductExceptionCode.CART_NOT);
        }
        //判断有要下单的商品是否存在于购物车
        for (Integer pInfoId : param.getPInfoIds()) {
            if (redisUtil.zscore(RedisKey.userCart(param.getUserId()), pInfoId + "") == null) {
                throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_CART_NOT_THIS_PRODUCT);
            }
        }
        //获取购物车存在的商品信息集合
        ArrayList<UserCartDto> userCartDtos = new ArrayList<>();
        for (UserCartDto userCartDto : cartDtos) {
            for (Integer pInfoId : param.getPInfoIds()) {
                if (userCartDto.getPInfoId().equals(pInfoId)) {
                    userCartDtos.add(userCartDto);
                }
            }
        }
        //上锁
        //创建多个单锁
        RLock[] locks = new RLock[userCartDtos.size()];
        int index = 0;
        for (UserCartDto userCartDto : userCartDtos) {
            RLock l = redissonClient.getFairLock(RedisKey.orderProductLock(userCartDto.getPInfoId() + ""));
            locks[index++] = l;
        }
        //使用数组创建多资源锁
        RLock lock = redissonClient.getMultiLock(locks);
        try {
            //(商品订单编号)雪花数随机生成商品编号 日期转换器
            String orderProductNum = new Snowflake(1, 1).nextIdStr();
            //判断商品是否还存有余量
            for (UserCartDto cartDto : userCartDtos) {
                Result<ProductInfoDto> productInfoDtoResult = productClient.findProductInfoById(cartDto.getPInfoId());
                if (productInfoDtoResult.getCode() != 200) {
                    throw new WoniuException(productInfoDtoResult.getMsg(), productInfoDtoResult.getCode());
                }
                if (productInfoDtoResult.getData().getRestNum().compareTo(BigDecimal.valueOf(cartDto.getCartNumber())) < 0) {
                    throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_NUMBER_NO_HAVE);
                }
            }
            System.out.println("ids:"+param.getPInfoIds());
            //（订单金额）初次计算订单总价
            BigDecimal orderPrice =new BigDecimal(0.0);
            System.out.println("userCartDtos:"+userCartDtos);
            for (UserCartDto userCartDto : userCartDtos) {
                //判断商品是否参与活动
                System.out.println("userCartDto:"+userCartDto);
                Result<List<ProductActiveDto>> productActiveListResult = productClient.findAllActiveByItemId(userCartDto.getPItemId());
                List<ProductActiveDto> activeDtos = new ArrayList<>();
                if(productActiveListResult.getCode()==200){
                    activeDtos=productActiveListResult.getData();
                }
                System.out.println("activeDtos"+activeDtos);
                if (activeDtos.size()>0) {
                    for (ProductActiveDto activeDto : activeDtos) {
                        if (activeDto.getEndTime().isAfter(LocalDateTimeUtil.parse(param.getOrderTime())) && activeDto.getStartTime().isBefore(LocalDateTimeUtil.parse(param.getOrderTime()))) {
                            System.out.println(userCartDto.getPInfoPrice());
                            System.out.println("activeDto:"+activeDto);
                            userCartDto.setPInfoPrice(userCartDto.getPInfoPrice().multiply(activeDto.getCutDownPercent()));
                        }
                    }
                    System.out.println(orderPrice+"+"+userCartDto.getPInfoPrice().multiply(BigDecimal.valueOf(userCartDto.getCartNumber())));
                    orderPrice=orderPrice.add(userCartDto.getPInfoPrice().multiply(BigDecimal.valueOf(userCartDto.getCartNumber())));
                    System.out.println("orderPrice1:"+orderPrice);
                }else{
                    System.out.println(orderPrice+"+"+userCartDto.getPInfoPrice().multiply(BigDecimal.valueOf(userCartDto.getCartNumber())));
                    orderPrice=orderPrice.add(userCartDto.getPInfoPrice().multiply(BigDecimal.valueOf(userCartDto.getCartNumber())));
                    System.out.println("orderPrice2:"+orderPrice);
                }


            }
            System.out.println("orderPrice:"+orderPrice);
            ////查询用户vip 判断是否享受vip优惠
            Result<UserVipDto> vipResult = valueAddedClient.getUserVipInfo(param.getUserId());
            UserVipDto vipDto = null;
            if (vipResult.getCode() == 200) {
                vipDto = vipResult.getData();
            }
            if (vipDto != null && vipDto.getVipEndTime().isAfter(LocalDateTimeUtil.parse(param.getOrderTime())) && vipDto.getVipStartTime().isBefore(LocalDateTimeUtil.parse(param.getOrderTime(), "yyyy-MM-dd HH:mm:ss"))) {
                orderPrice=orderPrice.multiply(BigDecimal.valueOf(0.95));
            }
            ////查询优惠卷信息
            if (param.getTicketId() != null) {
                System.out.println("userId："+param.getUserId());
                Result<UserTicketDto> userTicketDtoResult = valueAddedClient.checkUserTicketId(param.getUserId(), param.getTicketId());
                System.out.println(userTicketDtoResult.getMsg());
                if (userTicketDtoResult.getCode() != 200) {
                    throw new WoniuException(userTicketDtoResult.getMsg(), userTicketDtoResult.getCode());
                }
                UserTicketDto ticketDto = userTicketDtoResult.getData();
                System.out.println("ticket:"+ticketDto);
                if (vipDto != null && vipDto.getVipLevelId() < ticketDto.getAllowVipLevel()) {
                    throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_VIP_NO_ACCORD);
                }
                if (ticketDto.getCreateTime().plusDays(ticketDto.getLimitTime()).isBefore(LocalDateTimeUtil.parse(param.getOrderTime()))) {
                    throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_TICKET_TIME_OVERED);
                }
                System.out.println(orderPrice);
                if (orderPrice.compareTo(ticketDto.getAllowUsePrice()) < 0) {
                    throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_TICKET_NO_ACCORD_PRICE);
                }
                orderPrice=orderPrice.subtract(ticketDto.getCutDownPrice());
            }
            //（地址信息）准备地址
            Result<AddressInfoDto> addressInfoDtoResult = extraClient.AddressInfoById(param.getAddressId());
            if (addressInfoDtoResult.getCode() != 200) {
                throw new WoniuException(addressInfoDtoResult.getMsg(), addressInfoDtoResult.getCode());
            }
            AddressInfoDto addressInfoDto = addressInfoDtoResult.getData();

            //执行下单
            OrderProduct orderProduct = new OrderProduct();
            //当orderPrice小于0时
            if(orderPrice.compareTo(BigDecimal.valueOf(0))<0){
                orderPrice=BigDecimal.valueOf(0);
            }
            orderProduct.setOrderProductNum(orderProductNum);
            System.out.println(orderProductNum);
            orderProduct.setOrderPrice(orderPrice);
            orderProduct.setUserId(param.getUserId());
            orderProduct.setAddressId(addressInfoDto.getAddressId());
            orderProduct.setOrderTime(LocalDateTimeUtil.parse(param.getOrderTime()).toString());
            orderProduct.setOrderProductState(StaticData.ORDER_PRODUCT_STATE_NO_PAID);
            orderProduct.setReviewState(0);
            orderProductMapper.insert(orderProduct);

            //详情存入redis
            for (UserCartDto userCartDto : userCartDtos) {
                redisUtil.sAdd(RedisKey.orderProductPInfoSet(orderProductNum), userCartDto.getPInfoId() + "");
                try {
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("pInfoId", userCartDto!=null?userCartDto.getPInfoId().toString():"");
                    map.put("pInfoName", userCartDto.getPInfoName());
                    map.put("pItemId", userCartDto!=null?userCartDto.getPItemId().toString():"");
                    map.put("pName", userCartDto.getPName());
                    map.put("pTName", userCartDto.getPTName());
                    map.put("pBName", userCartDto.getPBName());
                    map.put("pInfoPrice", userCartDto.getPInfoPrice().toString());
                    map.put("pDetails", userCartDto.getPDetails());
                    map.put("pPicture", userCartDto.getPPicture());
                    map.put("number", userCartDto!=null?userCartDto.getCartNumber().toString():"");
                    redisUtil.hmset(RedisKey.orderProductPInfoByNumHash(orderProductNum, userCartDto.getPInfoId()), map);
                } catch (Exception e) {
                    redisUtil.sRem(RedisKey.orderProductPInfoSet(orderProductNum), userCartDto.getPInfoId().toString());
                    throw e;
                }
                //修改商品的余量和冻结量
                SuccessfulOrderForm successfulOrderForm = new SuccessfulOrderForm();
                successfulOrderForm.setNum(userCartDto.getCartNumber());
                successfulOrderForm.setPInfoId(userCartDto.getPInfoId());
                productClient.successfulOrder(successfulOrderForm);

                //消耗优惠卷
                valueAddedClient.reduceUserTicket(param.getUserId(),param.getTicketId(),1);

                //删除redis中购物车的信息
                redisUtil.zrem(RedisKey.userCart(param.getUserId()), userCartDto.getPInfoId() + "");
                redisUtil.delete(RedisKey.userCartGoods(param.getUserId(), userCartDto.getPInfoId()));

                //死信 将订单编号发送到延迟队列中,未支付过期自动取消
                rabbitTemplate.convertAndSend("order_product_del_delay_queue",orderProductNum);
            }
        } finally {
            lock.unlock();
        }
        return true;
    }

    @Override
    public String pay(String orderProductNum, String userId) throws Exception {
        //查询订单详情
        OrderProduct orderProduct = orderProductMapper.selectOne(new QueryWrapper<OrderProduct>().eq("order_product_num",orderProductNum));
        //判断订单是否属于本人
        if (orderProduct == null) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NULL);
        }
        if (!orderProduct.getUserId().equals(userId)) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_USER_NO_PAY);
        }
        if (!orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_NO_PAID)) {
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PAYED);
        }
        //调用
        PagePayParam payParam = new PagePayParam();
        //以下参数根据实际情况设置
        payParam.setOrderId(UUID.randomUUID().toString().replace("-", ""));
        payParam.setSubject("汽车服务");
        payParam.setBody("汽车服务订单支付");
        payParam.setOrderId(orderProductNum);
        payParam.setMoney(orderProduct.getOrderPrice().doubleValue());
        payParam.setReturnUrl("http://localhost:80/swagger-ui.html");

        //内网穿透 记得修改
        payParam.setNotifyUrl(" http://h5mdc4.natappfree.cc/order/orderProduct/payNotify");

        //取出数据库订单的下单时间
        System.out.println("下单时间" + orderProduct.getOrderTime());
//        LocalDateTime localDateTime = LocalDateTimeUtil.parse(orderProduct.getOrderTime());
        LocalDateTime localDateTime =LocalDateTimeUtil.parse(orderProduct.getOrderTime(), "yyyy-MM-dd HH:mm:ss");
        long expireTime = java.sql.Date.from(localDateTime.plusMinutes(15).atZone(ZoneId.systemDefault()).toInstant()).getTime();
        long now = new java.util.Date().getTime();
        int minute = (int) ((expireTime - now) / 1000 / 60);
        System.out.println(expireTime + " " + minute);
        if (minute < 1) {
            throw new OrderProductException(45566, "订单超时");
        }
        java.util.Date date = new java.util.Date(expireTime);
        String expire = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        payParam.setTimeExpire(expire);

        //调用接口
        String pay = alipayUtil.pagePay(payParam);
        return pay;
    }

    @Override
    public void payNotify(Map<String, String> params) throws AlipayApiException {
        //在异步回调业务层验签 防止伪造请求
        System.out.println("params:" + params);
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfiguration.getAlipayPublicKey(), "utf-8", "RSA2"); //调用SDK验证签名
        if (signVerified) {
            //验签通过
            //取出订单编号
            String orderProductNum = params.get("out_trade_no");
            OrderProduct orderProduct = orderProductMapper.selectOne(new QueryWrapper<OrderProduct>().eq("order_product_num",orderProductNum));
            String tradeStatus = params.get("trade_status");
            if (orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_NO_PAID)) {
                String payTimeStr = params.get("gmt_payment");
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                LocalDateTime payTime = LocalDateTime.parse(payTimeStr, formatter);
                orderProduct.setPayTime(String.valueOf(payTime));

                ArrayList<Map<Object, Object>> maps = selectProductInfosByOrderProductNum(orderProductNum);
                //修改冻结量+销量
                for (Map<Object,Object> map:maps){
                    //修改冻结量
                    SuccessfulSaleForm form = new SuccessfulSaleForm();
                    form.setPInfoId(Integer.valueOf(map.get("pInfoId").toString()));
                    form.setNum(Integer.valueOf(map.get("number").toString()));
                    productClient.successfulSale(form);
                    //增加销量
                    productClient.addPInfoNum(Integer.valueOf(map.get("pInfoId").toString()));
                }
                //用户积分
                personClient.addUserScore(orderProduct.getUserId(),orderProduct.getOrderPrice().intValue(),StaticData.SCORE_SHOPPING);
                //订单状态
                orderProduct.setOrderProductState(StaticData.ORDER_PRODUCT_STATE_PAID);
                orderProductMapper.updateById(orderProduct);
            }
        }
    }

    @Override
    public Boolean refund(String orderProductNum,String userId) throws AlipayApiException {
        OrderProduct orderProduct = orderProductMapper.selectOne(new QueryWrapper<OrderProduct>().eq("order_product_num",orderProductNum));
        //登录用户是否能操作
        if(!orderProduct.getUserId().equals(userId)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_USER_NOT_POWER);
        }
        if((!orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_NO_GET))&&(!orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_PAID))){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_NO_DIRECT_REFUND);
        }
        if(orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_REFUND_FINISHED)||orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_REFUND_WAIT)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_NO_REPEAT_REFUND);
        }
        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
        String out_trade_no=orderProductNum;
        String refund_reason="未发货,无理由退货";
        //标识一次退款请求，同一笔交易分多次退款的话，out_request_no每次传值都不能重复，必须保证唯一性

        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"refund_amount\":\""+ orderProduct.getOrderPrice() +"\","
                + "\"refund_reason\":\""+ refund_reason +"\","
                + "\"out_request_no\":\""+ UUID.randomUUID()+"\"}");
        String result=alipayClient.execute(alipayRequest).getBody();
//        String code = JSONUtil.parseObj(JSONUtil.parseObj(result).get("alipay_trade_refund_response").toString()).get("code").toString();
//        String fundChange = JSONUtil.parseObj(JSONUtil.parseObj(result).get("alipay_trade_refund_response").toString()).get("fund_change").toString();

        try {
            AlipayTradeRefundResponse response = alipayClient.execute(alipayRequest);
            if(response.isSuccess()){
                //退款操作
                //扣除积分
                personClient.reduceUserScore(userId,orderProduct.getOrderPrice().intValue(),StaticData.SCORE_SHOPPING);
                //还商品余量
                ArrayList<Map<Object, Object>> maps = selectProductInfosByOrderProductNum(orderProductNum);
                for (Map<Object,Object> map:maps){
                    String pInfoId = map.get("pInfoId").toString();
                    String productNum = map.get("number").toString();
                    FailedSaleForm form = new FailedSaleForm();
                    form.setNum(Integer.parseInt(productNum));
                    form.setPInfoId(Integer.parseInt(pInfoId));
                    productClient.failedSale(form);
                }
                //修改订单退款状态
                orderProduct.setOrderProductState(StaticData.ORDER_PRODUCT_STATE_REFUND_FINISHED);
                orderProductMapper.updateById(orderProduct);
                return true;
            }else {
                return false;
            }
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean updateReviewStateByOrderProductNum(OrderProductUpdateReviewStateForm form) {
        OrderProduct orderProduct = orderProductMapper.selectById(form.getOrderProductNum());
        if(orderProduct==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NULL);
        }
        if(orderProduct.getOrderProductState().equals(StaticData.SCORE_USED)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_SCORE_USED);
        }
        orderProduct.setOrderScore(form.getOrderScore());
        orderProduct.setReviewState(StaticData.SCORE_USED);
        orderProductMapper.updateById(orderProduct);
        return true;
    }

    @Override
    public Boolean finishOrder(String orderProductNum, String userId) {
        OrderProductDto orderProductDto = selectOneOrderByOrderNum(orderProductNum);
        if(orderProductDto==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NULL);
        }
        if(orderProductDto.getOrderProductState().equals(StaticData.ORDER_SERVICE_STATE_FINISHED)||orderProductDto.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_AFTER_SALES)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_FINISHED);
        }
        if(!orderProductDto.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_NO_GET)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NOT_FINISHED);
        }
        if(!userId.equals(orderProductDto.getUserId())){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_USER_NOT_POWER);
        }
        OrderProduct orderProduct = orderProductMapper.selectById(orderProductNum);
        orderProduct.setOrderProductState(StaticData.ORDER_PRODUCT_STATE_AFTER_SALES);
        orderProductMapper.updateById(orderProduct);
        return true;
    }

    @Override
    public Boolean upOrder(String orderProductNum) {
        OrderProductDto orderProductDto = selectOneOrderByOrderNum(orderProductNum);
        if(orderProductDto==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NULL);
        }
        if(orderProductDto.getOrderProductState().equals(StaticData.ORDER_SERVICE_STATE_FINISHED)||orderProductDto.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_AFTER_SALES)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_FINISHED);
        }
        OrderProduct orderProduct = orderProductMapper.selectById(orderProductNum);
        orderProduct.setOrderProductState(StaticData.ORDER_PRODUCT_STATE_NO_GET);
        orderProductMapper.updateById(orderProduct);
        return true;
    }
}
